package com.zygh.lz.controller.pc;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zygh.lz.entity.Equipage;
import com.zygh.lz.entity.SchedulingInformation;
import com.zygh.lz.entity.VehicleCoordinate;
import com.zygh.lz.service.SchedulingInfoService;
import com.zygh.lz.service.VehicleCoordinateService;
import com.zygh.lz.service.impl.EquipageServiceImpl;
import com.zygh.lz.stapprove.ResultUtil;
import com.zygh.lz.util.DateUtils;
import com.zygh.lz.vo.ResultBean;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import net.jodah.expiringmap.ExpirationPolicy;
import net.jodah.expiringmap.ExpiringMap;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @Author: shuaiqi
 * @CreateTime: 2022-12-24  14:40
 */
@Api(tags = "清障车管理")
@RestController
@RequestMapping("/roadRescue")
@Slf4j
public class RoadRescueController {

    public static final String DATETIME_CONVENTIONAL_CN = "yyyy-MM-dd HH:mm:ss";

    @Resource
    private SchedulingInfoService schedulingInfoService;
    @Resource
    private VehicleCoordinateService vehicleCoordinateService;
    @Resource
    private EquipageServiceImpl equipageService;

    private static final Long timeOut = 7100l;

    /**
     * 存储车辆总数量的map
     */
    private static final ExpiringMap<String, Integer> carCountMap = ExpiringMap.builder()
            // 设置每个key有效时间,单位秒
            .expiration(timeOut, TimeUnit.SECONDS)
            // 允许更新过期时间值
            .variableExpiration()
            // CREATED: 只在put和replace方法重置过期时间
            .expirationPolicy(ExpirationPolicy.CREATED).build();

    /**
     * 接收排班信息
     */
    @PostMapping(value = "/acceptSchInf", produces = "application/json;charset=utf-8")
    public String acceptSchInf(HttpServletRequest req, HttpServletResponse resp) throws IOException, ParseException {
        log.info("每十五分钟接收清障车排班信息");
        //设置返回值类型和编码
        resp.setContentType("text/html;charSet=utf-8");
        String requestJson = "";
        // 获取post请求的输入流读取器
        // 以流的形式接受上来的数据，并指定编码方式
        BufferedReader br = new BufferedReader(new InputStreamReader(req.getInputStream(), "UTF-8"));
        // 将输入流转换成字符串
        StringBuffer sb = new StringBuffer();
        String temp;
        while ((temp = br.readLine()) != null) {
            sb.append(temp);
        }
        br.close(); // 关闭读取器
        //接收到的数据
        requestJson = sb.toString();
        //将排班信息批量插入数据表
        //转成数组
        JSONArray jsonArray = JSONObject.parseArray(requestJson);
        //排班信息集合
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = JSONObject.parseObject(jsonArray.get(i).toString());
            //JSON转成实体类
            SchedulingInformation schedulingInformation = JSONObject.toJavaObject(jsonObject, SchedulingInformation.class);
            //日期格式化
            LocalDateTime date = LocalDateTime.parse(schedulingInformation.getStart_at(), DateTimeFormatter.ISO_OFFSET_DATE_TIME);
            String startAtDate = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            schedulingInformation.setStart_at(startAtDate);
            LocalDateTime date1 = LocalDateTime.parse(schedulingInformation.getEnd_at(), DateTimeFormatter.ISO_OFFSET_DATE_TIME);
            String endAtDate = date1.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            schedulingInformation.setEnd_at(endAtDate);
            schedulingInformation.setGmt_create(DateUtil.now());

            schedulingInformation.setPoint_name(schedulingInformation.getPoint_name().replaceAll("\\s", ""));
            //设置时间段
            //获取当前的日期，格式：yyyy-MM-dd
            String today = DateUtil.today();
            if (startAtDate.equals(today + " 07:00:00") && endAtDate.equals(today + " 09:00:00")) {
                //早高峰
                schedulingInformation.setTimeBucket(0);
            } else if (startAtDate.equals(today + " 09:00:00") && endAtDate.equals(today + " 17:00:00")) {
                //平峰期
                schedulingInformation.setTimeBucket(1);
            } else if ((startAtDate.equals(today + " 17:00:00") && endAtDate.equals(today + " 19:00:00")) || (startAtDate.equals(today + " 17:30:00") && endAtDate.equals(today + " 19:30:00"))) {
                //晚高峰
                schedulingInformation.setTimeBucket(2);
            }
            //将排班数据集合插入到数据表中
            schedulingInfoService.saveOrUpdate(schedulingInformation, Wrappers.<SchedulingInformation>lambdaUpdate()
                    .eq(SchedulingInformation::getPoint_name, schedulingInformation.getPoint_name())
                    .eq(SchedulingInformation::getNumber, schedulingInformation.getNumber())
                    .eq(SchedulingInformation::getTimeBucket, schedulingInformation.getTimeBucket())
                    .between(SchedulingInformation::getGmt_create, DateUtils.getDayBegin(), DateUtils.getDayEnd()));
        }
        //排班信息的JSON数据
        return requestJson;
    }

    /**
     * 接收车辆总数量
     */
    @PostMapping(value = "/acceptCarCount", produces = "application/json;charset=utf-8")
    public void acceptCarCount(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        log.info("每俩小时接收车辆总数量");
        //设置返回值类型和编码
        resp.setContentType("text/html;charSet=utf-8");
        String requestJson = "";
        // 获取post请求的输入流读取器
        // 以流的形式接受上来的数据，并指定编码方式
        BufferedReader br = new BufferedReader(new InputStreamReader(req.getInputStream(), "UTF-8"));
        // 将输入流转换成字符串
        StringBuffer sb = new StringBuffer();
        String temp;
        while ((temp = br.readLine()) != null) {
            sb.append(temp);
        }
        br.close(); // 关闭读取器
        //接收到的数据
        requestJson = sb.toString();
        JSONObject jsonObject = JSONObject.parseObject(requestJson);
        //存储在map中
        carCountMap.put("carCount", (Integer) jsonObject.get("car_count"));
    }

    /**
     * 接收车辆定位信息
     */
    @PostMapping(value = "/acceptVehMsg", produces = "application/json;charset=utf-8")
    public String acceptVehMsg(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        log.info("每分钟接收清障车车辆定位");
        //设置返回值类型和编码
        resp.setContentType("text/html;charSet=utf-8");
        String requestJson = "";
        // 获取post请求的输入流读取器
        // 以流的形式接受上来的数据，并指定编码方式
        BufferedReader br = new BufferedReader(new InputStreamReader(req.getInputStream(), StandardCharsets.UTF_8));
        // 将输入流转换成字符串
        StringBuffer sb = new StringBuffer();
        String temp;
        while ((temp = br.readLine()) != null) {
            sb.append(temp);
        }
        br.close(); // 关闭读取器
        //接收到的数据
        requestJson = sb.toString();
        //System.out.println("requestJson:=========="+requestJson);
        //转成数组
        //JSONArray jsonArray = JSONObject.parseArray(requestJson);  使用这个本地正常，线上报错unclosed.str
        //List<VehicleCoordinate> vehicleCoordinateList = JSONObject.parseArray(requestJson, VehicleCoordinate.class);

        cn.hutool.json.JSONArray array = JSONUtil.parseArray(requestJson);
        ///System.out.println("array:=========="+array);
        List<VehicleCoordinate> vehicleCoordinateList = JSONUtil.toList(array, VehicleCoordinate.class);
        //System.out.println("vehicleCoordinateList:=========="+vehicleCoordinateList.toString());

        //排班信息集合
        for (VehicleCoordinate vehicleCoordinate : vehicleCoordinateList) {
            //JSONObject jsonObject = JSONObject.parseObject(jsonArray.get(i).toString());
            //JSON转成实体类
            //VehicleCoordinate vehicleCoordinate = JSONObject.toJavaObject(jsonObject, VehicleCoordinate.class);
            //将GPS定位时间秒级转为标准时间
            if (vehicleCoordinate.getGps_time() != null) {
                String gps_time = vehicleCoordinate.getGps_time();
                Long gpsTime = Long.valueOf(gps_time);
                Long timestamp = gpsTime * 1000;  // 秒级* 1000 = 毫秒级
                String dateStr = com.zygh.lz.util.DateUtil.timestampToDateStr(timestamp, DATETIME_CONVENTIONAL_CN);
                vehicleCoordinate.setGps_time(dateStr);
                vehicleCoordinate.setGmt_create(DateUtil.now());
                //将车辆定位信息插入到表中
                vehicleCoordinateService.save(vehicleCoordinate);
            }
        }
        return requestJson;
    }

    @ApiOperation("获取当天清障车排班信息")
    @GetMapping
    public ResultBean selectAll() {
        return ResultUtil.setOK("success", schedulingInfoService.selectAll());
    }

    @ApiOperation("根据车牌号和车牌颜色查询车辆定位")
    @GetMapping("/getByNumber")
    public ResultBean getByNumber(@ApiParam(required = true, name = "number", value = "车牌号码")
                                  @RequestParam("number") String number,
                                  @ApiParam(required = true, name = "color", value = "车牌颜色")
                                  @RequestParam("color") String color) {
        return ResultUtil.setOK("success", vehicleCoordinateService.getByNumber(number, color));
    }

    @ApiOperation("获取当天清障车统计数据")
    @GetMapping("/getNums")
    public ResultBean getNums() {
        return ResultUtil.setOK("success", schedulingInfoService.getNums());
    }

    @ApiOperation("获取清障车实时在线信息")
    @GetMapping("/getInfo")
    public ResultBean getInfo() {
        return ResultUtil.setOK("success", schedulingInfoService.getInfo());
    }

    @ApiOperation("清障车按照时段和支队查询")
    @GetMapping("/getByTimeSection")
    public ResultBean getByTimeSection(@ApiParam(required = true, name = "pageNum", value = "当前页码")
                                       @RequestParam(defaultValue = "1", value = "pageNum") int pageNum,
                                       @ApiParam(required = true, name = "pageSize", value = "每页显示条数")
                                       @RequestParam(defaultValue = "10", value = "pageSize") int pageSize,
                                       @ApiParam(name = "timeBucket", value = "时段")
                                       @RequestParam(required = false, value = "timeBucket") Integer timeBucket,
                                       @ApiParam(name = "companyName", value = "部门名称")
                                       @RequestParam(required = false, value = "companyName") String companyName) {
        return ResultUtil.setOK("success", schedulingInfoService.getByTimeSection(pageNum, pageSize, timeBucket, companyName));
    }

    /**
     * 根据待命点和待命时段查询清障车详情
     *
     * @return
     */
    @ApiOperation("清障车待命点详情")
    @GetMapping("/getDetails")
    public ResultBean getDetails(@ApiParam(required = true, name = "pointName", value = "待命点")
                                 @RequestParam(value = "pointName") String pointName,
                                 @ApiParam(required = false, name = "timeBucket", value = "时段")
                                 @RequestParam(required = false, value = "timeBucket") Integer timeBucket) {
        return ResultUtil.setOK("success", schedulingInfoService.getDetails(pointName, timeBucket));
    }

    @ApiOperation("根据id查询清障车或者警车信息")
    @GetMapping("/getById")
    public ResultBean getById(@ApiParam(name = "id", value = "id")
                              @RequestParam("id") Integer id) {
        return ResultUtil.setOK("success", schedulingInfoService.getByIdAndNumber(id));
    }

    @ApiOperation("根据司机名称和车牌搜索清障车")
    @GetMapping("/getByDriver")
    public ResultBean getByDriver(@ApiParam(name = "driver", value = "车牌号码或者司机名称")
                                  @RequestParam("driver") String driver) {
        return ResultUtil.setOK("success", schedulingInfoService.getByDriver(driver));
    }

    @ApiOperation("根据警车车牌和单位搜索警车")
    @GetMapping("/getByCarNo")
    public ResultBean getByCarNo(@ApiParam(name = "carNo", value = "警车车牌和单位")
                                 @RequestParam("carNo") String carNo) {
        return ResultUtil.setOK("success", equipageService.getByCarNo(carNo));
    }

    @ApiOperation("删除上周清障车排班信息")
    @GetMapping("/delLastWeek")
    public ResultBean delLastWeek() {
        schedulingInfoService.deleteSchedulingInfo();
        return ResultUtil.setOK("success", null);
    }

    public Integer getCarCount() {
        return carCountMap.get("carCount");
    }
}
